package net.frenopatico.citadels.dao;

import java.util.List;
import java.util.Map;

import com.google.appengine.api.datastore.EntityNotFoundException;
import com.googlecode.objectify.Key;

/**
 * Interface for all the generic DAOs.
 *
 * @author eduardo.ramirez.ronco@gmail.com
 *
 * @param <T>
 */
public interface IGenericDAO<T> {

    /**
     * Saves the entity in the application context.
     *
     * @param entity Entity to put in the context.
     * @return The Key that identifies the saved entity.
     */
    Key<T> put( final T entity );

    /**
     *Saves the entities in the application context.
     *
     * @param entities Entities to save in the context.
     * @return Relation between the entities saved and their respective keys.
     */
    Map<Key<T>, T> put( final Iterable<T> entities );

    /**
     * Delete the entity from the application context.
     *
     * @param entity Entity to delete.
     */
    void delete( final T entity );

    /**
     * Delete the entity associated with the Key.
     *
     * @param entityKey Key of the entity to delete.
     */
    void delete( final Key<T> entityKey );

    /**
     * Delete the entities from the application context.
     *
     * @param entities Entities to delete.
     */
    void delete( final Iterable<T> entities );

    /**
     * Delete the entities associated with the Keys.
     *
     * @param keys Keys of the entities to delete.
     */
    void deleteKeys( final Iterable<Key<T>> keys );

    /**
     * Retrieve the entity with the id.
     *
     * @param entityId Id if the entity to retrieve.
     * @return The entity if found.
     * @throws EntityNotFoundException If the entity isn't found in the application context.
     */
    T get( final Long entityId ) throws EntityNotFoundException;

    /**
     * Retrieve the entity with the id.
     *
     * @param entityId Id if the entity to retrieve.
     * @return The entity if found.
     * @throws EntityNotFoundException If the entity isn't found in the application context.
     */
    T get( final String entityId ) throws EntityNotFoundException;

    /**
     * Retrieve the entity with this Key.
     *
     * @param key Key of the entity to retrieve.
     * @return The entity if found.
     * @throws EntityNotFoundException If the entity isn't found in the application context.
     */
    T get( final Key<T> key ) throws EntityNotFoundException;

    /**
     * Convenience method to generate a typed Key<T> for a given id
     *
     * @param entityId Id of the entity to generate the Key for.
     * @return The Key of the corresponding entity.
     */
    Key<T> getKey( final Long entityId );

    /**
     * Get ALL entities of type <T> in the datastore. Potentially very inefficient!! Make sure you have a good reason to use this!!
     *
     * @return All the entities if the type <T>.
     */
    List<T> listAll();

    /**
     * Obtain an entity with matching properties set in the example.
     *
     * @param example Entity to match properties against.
     * @return Entity with matching properties.
     */
    T getByExample( final T example );

    /**
     * Obtain entities with matching properties set in the example.
     *
     * @param example Entity to match properties against.
     * @return Entities with matching properties.
     */
    List<T> listByExample( final T example );

}
